import java.util.ArrayList;
import java.util.HashMap;

public class Expression extends Quaternion {
    private Pairs pair_a;
    private Pairs pair_b;
    private Pairs answer;
    private HashMap<String, Boolean> map = new HashMap<String, Boolean>();  //临时存储
    private static int index = 8;

    public Expression(Pairs pair_a, Pairs pair_b, OP op) {
        super(op);
        this.pair_a = pair_a;
        this.pair_b = pair_b;
    }

    public Pairs getPair_a() {
        return this.pair_a;
    }

    public Pairs getPair_b() {
        return this.pair_b;
    }

    public Pairs getAnswer() {
        return this.answer;
    }

    public void solveAnswer(int index) {
        switch (getOp()) {
            case ADD:
                this.answer = new Pairs(Pairs.Kind.VAL, useMap(index));
                if (pair_b.getInit() && pair_a.getInit()) {
                    this.answer.setValue(pair_a.getValue() + pair_b.getValue());
                }
                break;
            case DIV:
                this.answer = new Pairs(Pairs.Kind.VAL, useMap(index));
                if (pair_b.getInit() && pair_a.getInit()) {
                    if (pair_b.getValue() != 0)
                    this.answer.setValue(pair_a.getValue() / pair_b.getValue());
                }
                break;
            case MULT:
                this.answer = new Pairs(Pairs.Kind.VAL, useMap(index));
                if (pair_b.getInit() && pair_a.getInit()) {
                    this.answer.setValue(pair_a.getValue() * pair_b.getValue());
                }
                break;
            case MOD:
                this.answer = new Pairs(Pairs.Kind.VAL, useMap(index));
                if (pair_b.getInit() && pair_a.getInit()) {
                    if (pair_b.getValue() != 0)
                    this.answer.setValue(pair_a.getValue() % pair_b.getValue());
                }
                break;
            case SUB:
                this.answer = new Pairs(Pairs.Kind.VAL, useMap(index));
                if (pair_b.getInit() && pair_a.getInit()) {
                    this.answer.setValue(pair_a.getValue() - pair_b.getValue());
                }
                break;
            case SLT:
                this.answer = new Pairs(Pairs.Kind.VAL,useMap(index));
                if (pair_b.getInit() && pair_a.getInit()) {
                    this.answer.setValue(pair_a.getValue() < pair_b.getValue() ? 1 : 0);
                }
                break;
            case SLTIU:
                this.answer = new Pairs(Pairs.Kind.VAL,useMap(index));
                if (pair_b.getInit() && pair_a.getInit()) {
                    if (pair_a.getValue() != 0) {
                        this.answer.setValue(0);
                    } else {
                        this.answer.setValue(1);
                    }
                }
                break;
            case XOR:
                this.answer = new Pairs(Pairs.Kind.VAL,useMap(index));
                if (pair_b.getInit() && pair_a.getInit()) {
                    if (pair_b.getValue() == pair_a.getValue()) {
                        this.answer.setValue(0);
                    } else {
                        this.answer.setValue(1);
                    }
                }
                break;
        }
    }

    public void calculateAns() {
        switch (getOp()) {
            case ADD:
                if (pair_b.getInit() && pair_a.getInit()) {
                    this.answer.setValue(pair_a.getValue() + pair_b.getValue());
                }
                break;
            case DIV:
                if (pair_b.getInit() && pair_a.getInit()) {
                    this.answer.setValue(pair_a.getValue() / pair_b.getValue());
                }
                break;
            case MULT:
                if (pair_b.getInit() && pair_a.getInit()) {
                    this.answer.setValue(pair_a.getValue() * pair_b.getValue());
                }
                break;
            case MOD:
                if (pair_b.getInit() && pair_a.getInit()) {
                    this.answer.setValue(pair_a.getValue() % pair_b.getValue());
                }
                break;
            case SUB:
                if (pair_b.getInit() && pair_a.getInit()) {
                    this.answer.setValue(pair_a.getValue() - pair_b.getValue());
                }
                break;
            case SLT:
                break;
            case SLTIU:
                break;
        }
    }

    public String toString() {
        if (pair_a.getKind().equals(Pairs.Kind.ARRAY_VAR) || pair_a.getKind().equals(Pairs.Kind.ARRAY_VAL)) {
            if (pair_b.getKind().equals(Pairs.Kind.ARRAY_VAR) || pair_b.getKind().equals(Pairs.Kind.ARRAY_VAL)) {
                return answer.getToken() + " " + "=" + " " + pair_a.getToken() + "[" + pair_a.getParams().get(0).getToken() + "]" +
                        " " + opToString() + " " + pair_b.getToken() + "[" + pair_b.getParams().get(0).getToken() + "]" + "\n";
            } else {
                return answer.getToken() + " " + "=" + " " + pair_a.getToken() + "[" + pair_a.getParams().get(0).getToken() + "]" +
                        " " + opToString() + " " + pair_b.getToken() + "\n";
            }
        } else {
            if (pair_b.getKind().equals(Pairs.Kind.ARRAY_VAR) || pair_b.getKind().equals(Pairs.Kind.ARRAY_VAL)) {
                return answer.getToken() + " " + "=" + " " + pair_a.getToken() +
                        " " + opToString() + " " + pair_b.getToken() + "[" + pair_b.getParams().get(0).getToken() + "]" + "\n";
            } else {
                return answer.getToken() + " " + "=" + " " + pair_a.getToken() + " " + opToString() + " " + pair_b.getToken() + "\n";
            }
        }
    }

    public void initMap() {
        for (int i = 8; i <= 25; i++) {
            this.map.put("&" + i, false);
        }
    }

    public String useMap(int index) {
        map.put("&"+ index,true);
        String str = "&"+ index;
        /*if (index == 25) {
            index = 8;
        } else {
            index++;
        }*/
        return str;
    }
}
